package com.example.test.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;

/*
 * 该配置类用于自定义Spring异步任务的线程池。
 * 
 * 1. @EnableAsync 注解用于开启Spring对 @Async 注解的支持，
 *    使得被 @Async 标注的方法可以异步执行。
 * 2. 通过 @Bean(name = "taskExecutor") 定义了一个名为 taskExecutor 的线程池，
 *    供Spring异步任务调用。
 * 3. 线程池参数可灵活配置，提高并发处理能力。
 * 4. 若无此配置，Spring会使用默认线程池，无法自定义参数。
 */
@Configuration
@EnableAsync // 启用Spring对@Async注解的异步支持
public class AsyncConfig {

    /**
     * 定义一个名为 taskExecutor 的线程池Bean，供@Async异步任务使用。
     * 可通过调整参数优化并发性能。
     *
     * @return Executor 线程池执行器
     */
    @Bean(name = "taskExecutor")
    public Executor taskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10); // 核心线程数10
        executor.setMaxPoolSize(20);  // 最大线程数20
        executor.setQueueCapacity(500); // 任务队列容量500
        executor.setThreadNamePrefix("AsyncThread-"); // 线程名前缀，即这个线程池创建的所有线程都会带有这个前缀，便于排查问题
        executor.initialize(); // 初始化线程池
        return executor;
    }
 
    // 说明：
    // 本线程池未设置拒绝策略和线程工厂，原因如下：
    // 1. Spring 默认拒绝策略（AbortPolicy）即当线程池和队列都满时，直接抛出异常（RejectedExecutionException），已满足一般需求。
    // 2. ThreadPoolTaskExecutor 默认使用 Executors.defaultThreadFactory() 创建线程。
    // 3. 仅需特殊场景（如自定义线程属性，比如设置线程名、指定线程优先级、守护线程。拒绝处理方式。）时才需自定义。
    // 4. 当前配置简洁易维护，后续可根据实际需求扩展。
} 

// 补充说明：
    // 1. 实际项目中经常会有多个线程池，用于不同业务场景，因为不同的业务场景对并发、队列长度、线程数等有不同需求。（如异步任务、定时任务、消息处理等），以实现资源隔离和灵活调优。
    // 2. 通常在本配置类中通过多个 @Bean 方法分别定义不同的线程池，每个线程池有独立的名称和参数。
    //    示例：
    //    @Bean(name = "emailTaskExecutor")
    //    public Executor emailTaskExecutor() { ... }
    //    @Bean(name = "orderTaskExecutor")
    //    public Executor orderTaskExecutor() { ... }
    // 3. 在需要使用的地方通过 @Async("线程池名称") 指定具体线程池。（如 @Async("emailTaskExecutor") 或 @Async("orderTaskExecutor")）
    // 4. 线程池建议有明确命名和注释，便于维护和排查。（如 @Bean(name = "emailTaskExecutor") 或 @Bean(name = "orderTaskExecutor")）
    // 5.可以集中在一个配置类里管理所有线程池（如本文件），也可以根据业务模块分多个配置类。